<?php 
/**
 * @info Watajax JQUERY plugin server side
 * @author West Art Communication AB
 * @version 1.0
 * @changelog 
 * 		20100106 1.0 - First release
 * @usage
 * 		// SQL mode
 * 		$w = new WatajaxSql();
 *		$w->columns = array(
 *			"id" => array("name" => "#", "sort_type" => "numeric", "hide" => true),
 *			"firstname" => array("name" => "First name"),
 *			"lastname" => array("name" => "Last name"),
 *			"email" => array("name" => "E-mail adress", "transform" => "<a href=\"mailto:!email\">!email</a>"),
 *			"tools" => array("name" => "#", "virtual" => true, "transform" => "<a href=\"?edit=!id\">edit</a>")	
 *		);
 *		$w->run();
 * 		// Array mode is similiar, just use WatajaxArray and populate the $watajax->data array with your data instead.
 */
abstract class Watajax {

	public $columns = array();
	public $data = array();
	public $perPage = 10;
	public $page = 1;
	public $sortBy = NULL;
	public $sortOrder = "ASC";
	public $search = "";
	
	public function __construct() {
		$this->perPage = (is_numeric($_GET["watajax_per_page"])) ? $_GET["watajax_per_page"] : 10;
		$this->page = (is_numeric($_GET["watajax_page"])) ? $_GET["watajax_page"] : 1;
		$this->sortBy = ($_GET["watajax_sortBy"] != "") ? $_GET["watajax_sortBy"] : NULL;
		$this->sortOrder = ($_GET["watajax_sortOrder"] != "") ? $_GET["watajax_sortOrder"] : "ASC";
		$this->search = ($_GET["watajax_search"] != "") ? $_GET["watajax_search"] : "";
	}
	
	public function run() {
		$this->checkForAction();
	}
	
	public function checkForAction() {
		switch($_GET["action"]) {
			case "watajax_load_head":
				$this->sendHead();
				break;
			case "watajax_load_settings":
				echo json_encode($this->getSettings());
				break;
			case "watajax_load_body":
				$this->sendBody();
				break;
			default:
				break;
		}
	}
	
	public function getSettings() {
		return array("pages" => $this->getNumberOfPages());
	}

	abstract public function sortData();
	abstract public function getNumberOfPages();
	abstract public function getData();
	abstract public function searchFilterData();
		
	public function sendBody() {
		$this->sortData();
		$this->searchFilterData();
		$sorted_data = $this->getData();
	
		foreach($sorted_data as $row_id => $row_data) {
			echo "<tr id='$row_id'>";
			foreach($this->columns as $column_id => $column_data) {
				if ($this->columns[$column_id]["hide"] != true) {
					echo "<td id='".$column_id."_data'>".$row_data[$column_id]."</td>";
				}
			}
			echo "</tr>";
		}
	}
	
	public function sendHead() {
		echo "<tr>";
		foreach($this->columns as $id => $data) {
			if ($data["hide"] != true) {
				echo "<th id='$id'>".$data["name"]."</th>";
			}
		}		
		echo "</tr>";
	}
	
}

class WatajaxSql extends Watajax {
	
	protected $query = "";
	protected $database_table = "";
	protected $query_sort = ""; 
	protected $encoding = "UTF-8";
	protected $where = "";
	
	public function __construct($encoding = "UTF-8") { 
		parent::__construct();
		$this->encoding = $encoding;
		$this->table = $_GET["watajax_table"]; 
	}
	
	public function addWhere($where) {
		if ($this->where == "") {
			$this->where = " WHERE ";
		}
		$this->where .= $where." ";
	}
	
	public function searchFilterData() {
		if ($this->search != "") {
			$where = "";
			foreach($this->columns as $key => $value) {
				if ($value["virtual"] != true) {
					$where .= "`$key` LIKE '%".$this->search."%' OR ";
				}
			}
			$where = "(".rtrim($where, " OR ").")";
			$this->addWhere($where);
		}
	}
	
	public function sortData() {
		if ($this->sortBy != "") {
			$order = (strtoupper($this->sortOrder) == "ASC") ? "ASC" : "DESC";
			$this->query_sort = " ORDER BY `".mysql_real_escape_string($this->sortBy)."` ".$order;
		}
	}
	
	public function transformColumn($col, $data, $row) {
		$replace = array();
		foreach(array_keys($this->columns) as $k) {	$replace[] = "!".$k; }
		$data = ($this->encoding == "UTF-8") ? utf8_encode($data) : $data;
		if ($this->columns[$col]["transform"] != "") {
			$data = str_replace($replace, $row, $this->columns[$col]["transform"]);
		}
		return $data;
	}
	
	public function getData() {
		$data = array();
		$limit_start = (($this->page-1)*$this->perPage);
		$columns = array();
		foreach($this->columns as $key => $value) {
			if ($value["virtual"] != true) { $columns[] = $key; }
		}
		$sql = "SELECT `".implode("`,`", $columns)."` FROM `".mysql_real_escape_string($this->table)."`".$this->where.$this->query_sort." LIMIT ".$limit_start.",".$this->perPage;
		$r = mysql_query($sql);
		while($row = mysql_fetch_assoc($r)) {
			$fixed_row = array();
			foreach($this->columns as $key => $value) {
				$fixed_row[$key] = $this->transformColumn($key, $row[$key], $row);
			}
			$data[] = $fixed_row;
		}
		return $data;
	}
	
	function getNumberOfPages() {
		$sql = "SELECT COUNT(*) FROM `".mysql_real_escape_string($this->table)."`".$this->where;
		$num = @mysql_result(mysql_query($sql),0);
		return (is_numeric($num)) ? ceil($num / $this->perPage) : 0;
	}
}

class WatajaxArray extends Watajax {
	public function __construct() { parent::__construct(); }

	public function getNumberOfPages() {
		return ceil(count($this->data) / $this->perPage);
	}
	
	public function getData() {
		return array_slice($this->data, (($this->page-1)*$this->perPage), $this->perPage);
	}
	
	public function searchFilterData() {
		if ($this->search != "") {
			$this->data = $this->arr_search( $this->data, $this->search);
		}
	}	

	function arr_search( $data, $query ) {
	    $result = array();
	    foreach ($data as $row_id => $row_data) {
	    	foreach($row_data as $column) {
	    		if (stripos($column, $query) !== false) {
	    			$result[$row_id] = $row_data;
	    		}
	    	}
	    }
	    return $result;
	} 
	
	public function sortData() {
		if ($this->sortBy != NULL) {
			$f='strcasecmp';
			$arr = $this->data;
			$l = $this->sortBy;
			if ($this->columns[$l]['sort_type']  == "numeric") {
				$function = "return (preg_replace('@\D@','',trim(strip_tags(\$a[$l]))) > preg_replace('@\D@','',trim(strip_tags(\$b[$l]))));";
			} else {
				$function = "return $f(trim(strip_tags(\$a[$l])), trim(strip_tags(\$b[$l])));";
			}
			usort($arr, create_function('$a, $b', $function));
			$this->data = (strtoupper($this->sortOrder) == "ASC") ? $arr : array_reverse($arr);
		}
	}
	
}

?>